package com.gitee.wsl.common.ui.ext


import kotlin.jvm.JvmOverloads


/*import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.graphics.Matrix
import androidx.graphics.shapes.RoundedPolygon
import androidx.graphics.shapes.TransformResult

*//**
 * Transforms a [RoundedPolygon] with the given [Matrix]
 *//*
fun RoundedPolygon.transformed(matrix: Matrix): RoundedPolygon =
    transformed { x, y ->
        val transformedPoint = matrix.map(androidx.compose.ui.geometry.Offset(x, y))
        TransformResult(transformedPoint.x, transformedPoint.y)
    }

*//**
 * Calculates and returns the bounds of this [RoundedPolygon] as a [Rect]
 *//*
fun RoundedPolygon.getBounds() = calculateBounds().let { Rect(it[0], it[1], it[2], it[3]) }*/


/*
data class ShapeItem(
    val name: String,
    val shapegen: () -> RoundedPolygon,
    val shapeDetails: String = "",
    val usesSides: Boolean = true,
    val usesInnerRatio: Boolean = true,
    val usesRoundness: Boolean = true,
    val usesInnerParameters: Boolean = true
)

class ShapeParameters(
    sides: Int = 5,
    innerRadius: Float = 0.5f,
    roundness: Float = 0f,
    smooth: Float = 0f,
    innerRoundness: Float = roundness,
    innerSmooth: Float = smooth,
    rotation: Float = 0f,
    shapeId: ShapeId = ShapeId.Polygon
) {
    internal val sides = mutableFloatStateOf(sides.toFloat())
    internal val innerRadius = mutableFloatStateOf(innerRadius)
    internal val roundness = mutableFloatStateOf(roundness)
    internal val smooth = mutableFloatStateOf(smooth)
    internal val innerRoundness = mutableFloatStateOf(innerRoundness)
    internal val innerSmooth = mutableFloatStateOf(innerSmooth)
    internal val rotation = mutableFloatStateOf(rotation)

    internal var shapeIx by mutableIntStateOf(shapeId.ordinal)

    fun copy() = ShapeParameters(
        this.sides.value.roundToInt(),
        this.innerRadius.value,
        this.roundness.value,
        this.smooth.value,
        this.innerRoundness.value,
        this.innerSmooth.value,
        this.rotation.value,
        ShapeId.values()[this.shapeIx]
    )

    enum class ShapeId {
        Star, Polygon, Triangle, Blob, CornerSE
    }

    private fun rotationAsString() =
        if (this.rotation.value != 0f)
            "rotation = ${this.rotation.value}f, "
        else
            ""

    // Primitive shapes we can draw (so far)
    internal val shapes = listOf(
        ShapeItem("Star", shapegen = {
            RoundedPolygon.star(
                numVerticesPerRadius = this.sides.floatValue.roundToInt(),
                innerRadius = this.innerRadius.floatValue,
                rounding = CornerRounding(this.roundness.floatValue, this.smooth.floatValue),
                innerRounding = CornerRounding(
                    this.innerRoundness.floatValue,
                    this.innerSmooth.floatValue
                )
            )
        },
            shapeDetails = shapeDescription(id = "Star", sides = this.sides.floatValue.roundToInt(),
                innerRadius = innerRadius, roundness = roundness,
                smooth = smooth, innerRoundness = innerRoundness,
                innerSmooth = innerSmooth, rotation = rotation,
                code = "RoundedPolygon.star(numVerticesPerRadius = $sides, " +
                        "innerRadius = $innerRadius, rounding = CornerRounding($roundness, $smooth), " +
                        "innerRounding = CornerRounding($innerRoundness, $innerSmooth))")
        ),
        ShapeItem("Polygon", shapegen = {
            RoundedPolygon(
                numVertices = this.sides.floatValue.roundToInt(),
                rounding = CornerRounding(this.roundness.floatValue, this.smooth.floatValue),
            )
        },
            shapeDetails = shapeDescription(id = "Polygon",
                sides = this.sides.floatValue.roundToInt(),
                roundness = roundness, smooth = smooth, rotation = rotation,
                code = "RoundedPolygon(numVertices = ${this.sides.floatValue.roundToInt()}," +
                        "rounding = CornerRounding($roundness, $smooth))"
            ),
            usesInnerRatio = false, usesInnerParameters = false
        ),
        ShapeItem(
            "Triangle", shapegen = {
                val points = floatArrayOf(
                    radialToCartesian(1f, 270f.toRadians()).x,
                    radialToCartesian(1f, 270f.toRadians()).y,
                    radialToCartesian(1f, 30f.toRadians()).x,
                    radialToCartesian(1f, 30f.toRadians()).y,
                    radialToCartesian(this.innerRadius.floatValue, 90f.toRadians()).x,
                    radialToCartesian(this.innerRadius.floatValue, 90f.toRadians()).y,
                    radialToCartesian(1f, 150f.toRadians()).x,
                    radialToCartesian(1f, 150f.toRadians()).y
                )
                RoundedPolygon(
                    points,
                    CornerRounding(this.roundness.floatValue, this.smooth.floatValue),
                    centerX = 0f,
                    centerY = 0f
                )
            },
            shapeDetails = shapeDescription(id = "Triangle", innerRadius = innerRadius,
                smooth = smooth, rotation = rotation,
                code = "val points = floatArrayOf(" +
                        "    radialToCartesian(1f, 270f.toRadians()).x,\n" +
                        "    radialToCartesian(1f, 270f.toRadians()).y,\n" +
                        "    radialToCartesian(1f, 30f.toRadians()).x,\n" +
                        "    radialToCartesian(1f, 30f.toRadians()).y,\n" +
                        "    radialToCartesian($innerRadius, 90f.toRadians()).x,\n" +
                        "    radialToCartesian($innerRadius, 90f.toRadians()).y,\n" +
                        "    radialToCartesian(1f, 150f.toRadians()).x,\n" +
                        "    radialToCartesian(1f, 150f.toRadians()).y)\n" +
                        "RoundedPolygon(points, CornerRounding($roundness, $smooth), " +
                        "centerX = 0f, centerY = 0f)"
            ),
            usesSides = false, usesInnerParameters = false
        ),
        ShapeItem(
            "Blob", shapegen = {
                val sx = this.innerRadius.floatValue.coerceAtLeast(0.1f)
                val sy = this.roundness.floatValue.coerceAtLeast(0.1f)
                RoundedPolygon(
                    vertices = floatArrayOf(-sx, -sy,
                        sx, -sy,
                        sx, sy,
                        -sx, sy,
                    ),
                    rounding = CornerRounding(min(sx, sy), this.smooth.floatValue),
                    centerX = 0f, centerY = 0f
                )
            },
            shapeDetails = shapeDescription(id = "Blob", roundness = roundness,
                smooth = smooth, rotation = rotation,
                code = "val sx = $innerRadius.coerceAtLeast(0.1f)\n" +
                        "val sy = $roundness.coerceAtLeast(.1f)\n" +
                        "val verts = floatArrayOf(-sx, -sy, sx, -sy, sx, sy, -sx, sy)\n" +
                        "RoundedPolygon(verts, rounding = CornerRounding(min(sx, sy), $smooth)," +
                        "centerX = 0f, centerY = 0f)"),
            usesSides = false, usesInnerParameters = false),
        ShapeItem(
            "CornerSE", shapegen = {
                RoundedPolygon(
                    squarePoints(),
                    perVertexRounding = listOf(
                        CornerRounding(this.roundness.floatValue, this.smooth.floatValue),
                        CornerRounding(1f),
                        CornerRounding(1f),
                        CornerRounding(1f)
                    ),
                    centerX = 0f,
                    centerY = 0f
                )
            },
            shapeDetails = shapeDescription(id = "cornerSE", roundness = roundness,
                smooth = smooth, rotation = rotation,
                code = "RoundedPolygon(floatArrayOf(1f, 1f, -1f, 1f, -1f, -1f, 1f, -1f), " +
                        "perVertexRounding = listOf(CornerRounding($roundness, $smooth), " +
                        "CornerRounding(1f), CornerRounding(1f),  CornerRounding(1f))," +
                        "centerX = 0f, centerY = 0f)"),
            usesSides = false,
            usesInnerRatio = false,
            usesInnerParameters = false
        ),
        ShapeItem(
            "Circle", shapegen = {
                RoundedPolygon.circle(this.sides.floatValue.roundToInt())
            },
            shapeDetails = shapeDescription(id = "Circle", roundness = roundness,
                smooth = smooth, rotation = rotation,
                code = "RoundedPolygon.circle($sides)"),
            usesSides = true,
            usesInnerRatio = false,
            usesInnerParameters = false
        ),
        ShapeItem(
            "Rectangle", shapegen = {
                RoundedPolygon.rectangle(width = 4f, height = 2f,
                    rounding = CornerRounding(this.roundness.floatValue, this.smooth.floatValue),
                )
            },
            shapeDetails = shapeDescription(id = "Rectangle", numVerts = 4, roundness = roundness,
                smooth = smooth, rotation = rotation,
                code = "RoundedPolygon.rectangle(width = 4f, height = 2f, " +
                        "rounding = CornerRounding($roundness, $smooth))"),
            usesSides = false,
            usesInnerRatio = false,
            usesInnerParameters = false
        )
    )

    fun shapeDescription(
        id: String? = null,
        numVerts: Int? = null,
        sides: Int? = null,
        innerRadius: Float? = null,
        roundness: Float? = null,
        innerRoundness: Float? = null,
        smooth: Float? = null,
        innerSmooth: Float? = null,
        rotation: Float? = null,
        code: String? = null
    ): String {
        var description = "ShapeParameters:\n"
        if (id != null) description += "shapeId = $id, "
        if (numVerts != null) description += "numVertices = $numVerts, "
        if (sides != null) description += "sides = $sides, "
        if (innerRadius != null) description += "innerRadius = $innerRadius, "
        if (roundness != null) description += "roundness = $roundness, "
        if (innerRoundness != null) description += "innerRoundness = $innerRoundness, "
        if (smooth != null) description += "smoothness = $smooth, "
        if (innerSmooth != null) description += "innerSmooth = $innerSmooth, "
        if (rotation != null) description += "rotation = $rotation, "
        if (numVerts != null) description += "numVerts = $numVerts, "
        if (code != null) {
            description += "\nCode:\n$code"
        }
        return description
    }

    fun selectedShape() = derivedStateOf { shapes[shapeIx] }

    fun genShape(autoSize: Boolean = true) = selectedShape().value.shapegen().let { poly ->
        poly.transformed(Matrix().apply {
            if (autoSize) {
                val bounds = poly.getBounds()
                // Move the center to the origin.
                translate(
                    x = -(bounds.left + bounds.right) / 2,
                    y = -(bounds.top + bounds.bottom) / 2
                )

                // Scale to the [-1, 1] range
                val scale = 2f / max(bounds.width, bounds.height)
                scale(x = scale, y = scale)
            }
            // Apply the needed rotation
            rotateZ(rotation.floatValue)
        })
    }
}

private fun squarePoints() = floatArrayOf(1f, 1f, -1f, 1f, -1f, -1f, 1f, -1f)*/


/**
 * Creates a circular shape, approximating the rounding of the shape around the underlying
 * polygon vertices.
 *
 * @param numVertices The number of vertices in the underlying polygon with which to
 * approximate the circle, default value is 8
 * @param radius optional radius for the circle, default value is 1.0
 * @param centerX X coordinate of optional center for the circle, default value is 0
 * @param centerY Y coordinate of optional center for the circle, default value is 0
 *
 * @throws IllegalArgumentException [numVertices] must be at least 3
 */
//@JvmOverloads
//fun RoundedPolygon.Companion.circle(
//    numVertices: Int = 8,
//    radius: Float = 1f,
//    centerX: Float = 0f,
//    centerY: Float = 0f
//): RoundedPolygon {
//
//    if (numVertices < 3) throw IllegalArgumentException("Circle must have at least three vertices")
//
//    // Half of the angle between two adjacent vertices on the polygon
//    val theta = FloatPi / numVertices
//    // Radius of the underlying RoundedPolygon object given the desired radius of the circle
//    val polygonRadius = radius / cos(theta)
//    return RoundedPolygon(
//        numVertices, rounding = CornerRounding(radius), radius = polygonRadius,
//        centerX = centerX, centerY = centerY
//    )
//}

/**
 * Creates a rectangular shape with the given width/height around the given center.
 * Optional rounding parameters can be used to create a rounded rectangle instead.
 *
 * As with all [RoundedPolygon] objects, if this shape is created with default dimensions and
 * center, it is sized to fit within the 2x2 bounding box around a center of (0, 0) and will
 * need to be scaled and moved using [RoundedPolygon.transformed] to fit the intended area
 * in a UI.
 *
 * @param width The width of the rectangle, default value is 2
 * @param height The height of the rectangle, default value is 2
 * @param rounding The [CornerRounding] properties of every vertex. If some vertices should
 * have different rounding properties, then use [perVertexRounding] instead. The default
 * rounding value is [CornerRounding.Unrounded], meaning that the polygon will use the vertices
 * themselves in the final shape and not curves rounded around the vertices.
 * @param perVertexRounding The [CornerRounding] properties of every vertex. If this
 * parameter is not null, then it must be of size 4 for the four corners of the shape. If this
 * parameter is null, then the polygon will use the [rounding] parameter for every vertex instead.
 * The default value is null.
 * @param centerX The X coordinate of the center of the rectangle, around which all vertices will
 * be placed equidistantly. The default center is at (0,0).
 * @param centerY The X coordinate of the center of the rectangle, around which all vertices will
 * be placed equidistantly. The default center is at (0,0).
 */
//fun RoundedPolygon.Companion.rectangle(
//    width: Float = 2f,
//    height: Float = 2f,
//    rounding: CornerRounding = CornerRounding.Unrounded,
//    perVertexRounding: List<CornerRounding>? = null,
//    centerX: Float = 0f,
//    centerY: Float = 0f
//): RoundedPolygon {
//    val left = centerX - width / 2
//    val top = centerY - height / 2
//    val right = centerX + width / 2
//    val bottom = centerY + height / 2
//
//    return RoundedPolygon(
//        floatArrayOf(right, bottom, left, bottom, left, top, right, top),
//        rounding, perVertexRounding, centerX, centerY
//    )
//}

/**
 * Creates a star polygon, which is like a regular polygon except every other vertex is
 * on either an inner or outer radius. The two radii specified in the constructor must both
 * both nonzero. If the radii are equal, the result will be a regular (not star) polygon with twice
 * the number of vertices specified in [numVerticesPerRadius].
 *
 * @param numVerticesPerRadius The number of vertices along each of the two radii.
 * @param radius Outer radius for this star shape, must be greater than 0. Default value is 1.
 * @param innerRadius Inner radius for this star shape, must be greater than 0 and less
 * than or equal to [radius]. Note that equal radii would be the same as creating a
 * [RoundedPolygon] directly, but with 2 * [numVerticesPerRadius] vertices. Default value is .5.
 * @param rounding The [CornerRounding] properties of every vertex. If some vertices should
 * have different rounding properties, then use [perVertexRounding] instead. The default
 * rounding value is [CornerRounding.Unrounded], meaning that the polygon will use the vertices
 * themselves in the final shape and not curves rounded around the vertices.
 * @param innerRounding Optional rounding parameters for the vertices on the [innerRadius]. If
 * null (the default value), inner vertices will use the [rounding] or [perVertexRounding]
 * parameters instead.
 * @param perVertexRounding The [CornerRounding] properties of every vertex. If this
 * parameter is not null, then it must have the same size as 2 * [numVerticesPerRadius]. If this
 * parameter is null, then the polygon will use the [rounding] parameter for every vertex instead.
 * The default value is null.
 * @param centerX The X coordinate of the center of the polygon, around which all vertices will
 * be placed. The default center is at (0,0).
 * @param centerY The Y coordinate of the center of the polygon, around which all vertices will
 * be placed. The default center is at (0,0).
 *
 * @throws IllegalArgumentException if either [radius] or [innerRadius] are <= 0 or
 * [innerRadius] > [radius].
 */
//@JvmOverloads
//fun RoundedPolygon.Companion.star(
//    numVerticesPerRadius: Int,
//    radius: Float = 1f,
//    innerRadius: Float = .5f,
//    rounding: CornerRounding = CornerRounding.Unrounded,
//    innerRounding: CornerRounding? = null,
//    perVertexRounding: List<CornerRounding>? = null,
//    centerX: Float = 0f,
//    centerY: Float = 0f
//): RoundedPolygon {
//    if (radius <= 0f || innerRadius <= 0f) {
//        throw IllegalArgumentException("Star radii must both be greater than 0")
//    }
//    if (innerRadius >= radius) {
//        throw IllegalArgumentException("innerRadius must be less than radius")
//    }
//
//    var pvRounding = perVertexRounding
//    // If no per-vertex rounding supplied and caller asked for inner rounding,
//    // create per-vertex rounding list based on supplied outer/inner rounding parameters
//    if (pvRounding == null && innerRounding != null) {
//        pvRounding = (0 until numVerticesPerRadius).flatMap {
//            listOf(rounding, innerRounding)
//        }
//    }
//
//    // Star polygon is just a polygon with all vertices supplied (where we generate
//    // those vertices to be on the inner/outer radii)
//    return RoundedPolygon(
//        starVerticesFromNumVerts(numVerticesPerRadius, radius, innerRadius, centerX, centerY),
//        rounding, pvRounding, centerX, centerY)
//}
